﻿using Black.Surface2DEngine.Graphic2D;
using Black.Surface2DEngine.Graphic2D.Render2D;
using Black.Surface2DEngine.Input.Surface;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Black.Surface2DEngine.Graphic2D.Render2D.Process2D;
using Black.Surface2DEngine.Graphic2D.Render2D.Extensions;

namespace Black.Surface2DEngine.Test.Screens
{
    /// <summary>
    /// Ecran pour les types de sprites
    /// </summary>
    public class EntityScreen : Screen
    {
        #region Variables d'instances

        private Entity2DTexture m_oTouchOut;
        private Entity2DSprite m_oSprite;

        #endregion

        #region Fonctions protégées

        /// <summary>
        /// Charge les ressources
        /// </summary>
        protected override void LoadContent()
        {
            // Chargement des textures

            this.LoadRessource<Texture2D>("Fond01");
            this.LoadRessource<Texture2D>("Fond02");
            this.LoadRessource<Texture2D>("Fond03");
            this.LoadRessource<Texture2D>("Fond04");

            this.LoadRessource<Texture2D>("Square");
            this.LoadRessource<SpriteFont>("MasterFont");

            this.LoadRessource<Texture2D>("Vaisseau");
            this.LoadRessource<Sprite2DDef>("VaisseauAnim");
        }

        /// <summary>
        /// Crée les objets logique
        /// </summary>
        protected override void LoadLogic()
        {
            // Création du fond

            Entity2DParallaxe oParallaxe = this.Entity2DCreate<Entity2DParallaxe>(0.0f, 0.0f);
            oParallaxe.AddParallaxe(-1.0f, 0.0f, "Fond04");
            oParallaxe.AddParallaxe(-4.0f, 0.0f, "Fond01");
            oParallaxe.AddParallaxe(-10.0f, 0.0f, "Fond02");
            oParallaxe.AddParallaxe(-16.0f, 0.0f, "Fond03");

            // Création zone de sortie

            this.m_oTouchOut = this.Entity2DCreate<Entity2DTexture>(this.Graphic.ScreenWidth - 10, 10);
            this.m_oTouchOut.Texture = this.GetRessource<Texture2D>("Square");
            this.m_oTouchOut.SetAlign(Entity2DAlignHoriz.Right, Entity2DAlignVert.Top);

            Entity2DText oText = this.Entity2DCreate<Entity2DText>(this.Graphic.ScreenWidth - 65, 120);
            oText.SetAlign(Entity2DAlignHoriz.Right, Entity2DAlignVert.Top);
            oText.Text = "Touch to return";
            oText.Font = this.GetRessource<SpriteFont>("MasterFont");
            oText.Color = Color.Black;

            // Texte d'aide

            oText = this.Entity2DCreate<Entity2DText>(100.0f, 100.0f);
            oText.SetAlign(Entity2DAlignHoriz.Left, Entity2DAlignVert.Top);
            oText.Text = "Touch the screen to move starship";
            oText.Font = this.GetRessource<SpriteFont>("MasterFont");
            oText.Color = Color.White;

            // Création sprite
            // Il faut lui donner la texture et les données d'animations
            // Ensuite on défini la séquence d'animation a afficher
            // Les sprites peuvent être crées avec l'outil de sprite fournis en annexe

            this.m_oSprite = this.Entity2DCreate<Entity2DSprite>(200.0f, 200.0f);
            this.m_oSprite.Texture = this.GetRessource<Texture2D>("Vaisseau");
            this.m_oSprite.Definition = this.GetRessource<Sprite2DDef>("VaisseauAnim");
            this.m_oSprite.SetSequence("normal_normal", 50.0f, true, true);
        }

        /// <summary>
        /// Met à jour la logique de traitement de l'écran
        /// </summary>
        /// <param name="p_fTime">Indicateur temporel</param>
        protected override void UpdateOpen(float p_fTime)
        {
            // Recherche d'un contact sur une des zones

            foreach (TouchContact oContact in TouchManager._ContactsNew)
            {
                Rectangle oRect = new Rectangle((int)oContact.Contact.X, (int)oContact.Contact.Y, 2, 2);

                if (this.m_oTouchOut.Zone.Contains(oRect))
                {
                    this.Graphic.CreateScreen<MasterScreen>(true);
                    this.Close();
                }
                else
                    this.MoveStarship(oContact.Contact.X, oContact.Contact.Y);
            }
        }

        #endregion

        #region Fonctions privées

        /// <summary>
        /// Déplace le vaisseau a l'endroit indiqué
        /// </summary>
        private void MoveStarship(float p_fX, float p_fY)
        {
            // On arrête l'ancien déplacement si il existe

            Process2D oProcess = this.Process2DFind<Process2DTranslation>(this.m_oSprite);

            if (oProcess != null)
                oProcess.Kill();

            // On calcul le vecteur de déplacement

            Vector2 oMove = new Vector2(p_fX - this.m_oSprite.X, p_fY - this.m_oSprite.Y);

            // On démare un nouveau process

            oProcess = this.m_oSprite.Translation(oMove, 500.0f, false, false, null);
            oProcess.ProcessEnd += new System.EventHandler<Process2DArgs>(this.Process_ProcessEnd);

            // On change le sprite

            this.m_oSprite.SetSequence("avant_normal", 50.0f, true, true);
        }

        /// <summary>
        /// Se produit a la fin du déplacement du vaisseau
        /// </summary>
        /// <param name="sender">Source de l'appel</param>
        /// <param name="e">Argument de l'appel</param>
        private void Process_ProcessEnd(object sender, Process2DArgs e)
        {
            this.m_oSprite.SetSequence("normal_normal", 50.0f, true, true);
        }

        #endregion
    }
}
